package cn.remex.db;

import cn.remex.db.rsql.RsqlConstants;
import cn.remex.db.rsql.RsqlConstants.SqlOper;
import cn.remex.db.rsql.model.Modelable;
import cn.remex.db.sql.*;
import cn.remex.db.utils.CoreCvo;
import cn.remex.db.utils.Param;
import cn.remex.db.utils.reflect.ReflectUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

public class DbCvoBase<T extends Modelable, ParentType extends Modelable> extends CoreCvo {

	//====对外公开的API方法======================//
	public Consumer getRowConsumer() {
		return rowConsumer;
	}


	//====对外暴露使用的API属性，一般通过外部调用初始化生成======================//
	//基于lambda开发的数据操作功能而新增的属性，后面将以上功能逐步迁移过来结构化
	protected Class<T> beanClass;
	protected String spaceName;
	protected String beanName;
	protected String id;
	protected List<Order> orders = new ArrayList<>();
	protected Where<ParentType, T, T> filter = new Where<>();
	protected boolean doCount = false;
	protected boolean doPaging = false;
	protected int pagination = 1;
	protected int recordCount;
	protected int rowCount = 100;

	//====内部属性======================//
	protected Container container;
	protected boolean OK = false; //用来保存操作状态的
	protected SqlOper oper = SqlOper.list;
//	protected String dataType = RsqlConstants.DT_base + RsqlConstants.DT_object; // pickup querybyid均默认查询对象属性。
	protected String sqlString;
	protected Consumer rowConsumer;
	protected boolean updateByWhere;
	protected T bean;
	protected SqlColumn<ParentType, T, T, T> rootColumn;
	protected boolean _hasGroupBy = false;
	protected boolean _hasAggregateBy = false;
	private boolean _hasDistinct = false;
	protected Param _paramIndex = null;
	protected Param _tableIndex = null;
	protected String _tableAliasName = null;
	protected List<NamedParam> _namedParams;
	protected String _sqlString;
	protected String _prettySqlString;
	protected String _litterSqlString;
	protected boolean _isSubStatment;
	protected T _aopBean; //用于通过切面捕获lambda表达式中调用get方法而获得field的.
	protected String _executeMethod; //select;update;insert;delete
	protected DbCvo<ParentType,?> _supDbCvo;//上一级查询的


	//====内部方法======================//
	public void _setSupDbCvo(DbCvo<ParentType,?> _supDbCvo){this._supDbCvo = _supDbCvo;}
	public boolean _isRowConsumer() {
		return null!=rowConsumer;
	}
	public List<NamedParam> _getNamedParams() {
		return _namedParams;
	}
	public Param<Integer> _getParamIndex() {
		return _paramIndex;
	}
	public String _getPrettySqlString() {
		return this._prettySqlString;
	}
	public SqlColumn<ParentType, T, T, T> _getRootColumn() {
		return rootColumn;
	}
	public String _getSpaceName() {
		return this.spaceName;
	}
	public String _getSqlString() {
		return this._sqlString;
	}
	public String _getTableAliasName() {
		return _tableAliasName;
	}
	public Param<Integer> _getTableIndex() {
		return _tableIndex;
	}
	public boolean _isHasAggregateBy() {
		return _hasAggregateBy;
	}
	public boolean _isHasDistinct() {
		return _hasDistinct;
	}
	public void _setHasDistinct(boolean b) {
		_hasDistinct = true;
	}
	public boolean _isHasGroupBy() {
		return _hasGroupBy;
	}
	public boolean _isSubStatment() {
		return _isSubStatment;
	}
	public T _obtainAOPBean() {
		return _aopBean != null ? _aopBean : (_aopBean = ReflectUtil.createAopBean(beanClass));
	}
	public void _setHasAggregateBy(boolean _hasAggregateBy) {
		this._hasAggregateBy = _hasAggregateBy;
	}
	public void _setHasGroupBy(boolean b) {
		_hasGroupBy = b;
	}
	public void _setNamedParams(List<NamedParam> namedParams) {
		this._namedParams = namedParams;
	}
	public void _setParamIndex(Param<Integer> paramIndex) {
		this._paramIndex = paramIndex;
	}
	public void _setSpaceName(final String poolName) {
		this.spaceName = poolName;
	}
	public void _setSqlString(String sqlString) {
		this._sqlString = sqlString;
	}
	public void _setTableAliasName(String tableAliasName) {
		this._tableAliasName = tableAliasName;
	}
	public void _setTableIndex(Param<Integer> tableIndex) {
		this._tableIndex = tableIndex;
	}
	public void addOrder(final boolean sortable, final Object sidx, final String sord) {
		this.orders.add(new Order(sortable, sidx, sord));
	}
	public void addRule(final String field, final WhereRuleOper ruleOper, final Object value) {this.filter.addRule(field, ruleOper, value);}
	public void clear() {
		// 回收机制
//		this.sqlBean.clear();
//		this.sqlBean = null;
	}
	@Override
	public void putParameters(Map<String, Object> map) {
		if ($V("oper") != null) this.oper = $V("oper");
		if ($V("id") != null) this.id = $V("id");
		map.put(RsqlConstants.SYS_dataStatus, RsqlConstants.DS_managed);//datastatus列必须处理。

		super.putParameters(map);
	}


	//------------------getter & setter------------------------------//
	public Modelable getBean() {
		return this.bean;
	}
	public void setBean(T dbBean) {
		this.bean = dbBean;
	}
	public Class<T> getBeanClass() {
		return this.beanClass;
	}
	public void setBeanClass(Class<T> beanClass) {
		this.beanClass = beanClass;
	}
	public String getBeanName() {
		return this.beanName;
	}
	public void setBeanName(final String beanName) {
		this.beanName = beanName;
	}
	public Container getContainer() {
		return container;
	}
	public void setContainer(Container container) {
		this.container = container;
		this.spaceName = this.container.getSpaceName();
	}
//	public String getDataType() {
//		return this.dataType;
//	}
//	public void setDataType(final String dataType) {
//		this.dataType = dataType;
//	}
	public Where<ParentType, T,T> getFilter() {
		return this.filter;
	}
	public void setFilter(Where filter) {
		/**
		 * 通过ReflectUtils替换默认的SqlBeanWhere中的值。
		 *
		 */
		ReflectUtil.copyProperties(this.filter, filter, ReflectUtil.SPFeature.DeeplyCopy);
	}
	public String getId() {
		return this.id;
	}
	public void setId(final String id) {
		$S(RsqlConstants.SYS_id, id);
		this.id = id;
	}
	public SqlOper getOper() {
		return oper;
	}
	public void setOper(SqlOper oper) {
		this.oper = oper;
	}
	public List<Order> getOrders() {
		return this.orders;
	}
	public void setOrders(final List<Order> orders) {
		this.orders = orders;
	}
	public int getPagination() {
		return this.pagination;
	}
	public void setPagination(final int pagination) {
		this.setDoPaging(pagination > 0);
		this.setDoCount(pagination > 0);
		this.pagination = pagination;
	}
	public int getRecordCount() {
		return this.recordCount;
	}
	public void setRecordCount(int recordCount) {
		this.recordCount = recordCount;
	}
	public int getRowCount() {
		return this.rowCount;
	}
	public void setRowCount(final int rowCount) {
		this.setDoPaging(rowCount > 0);
		this.setDoCount(rowCount > 0);
		this.rowCount = rowCount;
	}
	public String getSqlString() {
		return this.sqlString;
	}
	public boolean isDoCount() {
		return this.doCount;
	}
	public void setDoCount(boolean doCount) {
		this.doCount = doCount;
	}
	public boolean isDoPaging() {
		return this.doPaging;
	}
	public void setDoPaging(boolean doPaging) {
		this.doPaging = doPaging;
	}
	public boolean isUpdateByWhere() {
		return updateByWhere;
	}
}
